{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# RegLin Synthesis\n",
    "\n",
    "Using linear regression for the synthesis of leads on the ECG\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Essential Libraries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.linear_model import LinearRegression"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Loading the ECG"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "samplePath = \"samples/1005639.txt\"\n",
    "\n",
    "ecgHeaders = [\n",
    "\t\"sample\",\n",
    "\t\"LI\", \n",
    "\t\"LII\", \n",
    "\t\"LIII\", \n",
    "\t\"aVR\", \n",
    "\t\"aVF\", \n",
    "\t\"aVL\",\n",
    "\t\"V1\",\n",
    "\t\"V2\",\n",
    "\t\"V3\",\n",
    "\t\"V4\",\n",
    "\t\"V5\",\n",
    "\t\"V6\"\n",
    "]\n",
    "\n",
    "ecgDf = pd.read_csv(samplePath)\n",
    "ecgDf.columns = ecgHeaders\n",
    "ecgDf = ecgDf.set_index(\"sample\")\n",
    "\n",
    "ecgDf.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Comparative Ecg Plot Function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def comparativeEcgPlot(ecg1, label1, ecg2, label2, title):\n",
    "\tplt.figure(figsize = (12, 6))\n",
    "\n",
    "\tplt.plot(ecg1, label = label1)\n",
    "\tplt.plot(ecg2, label = label2)\n",
    "\n",
    "\tplt.title(title)\n",
    "\n",
    "\tplt.xlabel(\"Amostra\")\n",
    "\tplt.ylabel(\"Dpp\")\n",
    "\n",
    "\tplt.legend()\n",
    "\n",
    "\tplt.show()\n",
    "\tplt.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Correlation analysis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "correlations = ecgDf.corr(method = \"pearson\")\n",
    "\n",
    "print(correlations)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "figure, axes = plt.subplots()\n",
    "\n",
    "image = axes.imshow(correlations, aspect = \"auto\")\n",
    "\n",
    "axes.set_title(\"Correlação entre as derivações\")\n",
    "\n",
    "axes.set_xticks(np.arange(12), labels = ecgHeaders[1:])\n",
    "axes.set_yticks(np.arange(12), labels = ecgHeaders[1:])\n",
    "\n",
    "for i in range(correlations.shape[0]):\n",
    "\tfor j in range(correlations.shape[1]):\n",
    "\t\tcorrelation = np.round(\n",
    "\t\t\tcorrelations.iloc[i, j], \n",
    "\t\t\t1\n",
    "\t\t)\n",
    "\n",
    "\t\taxes.text(\n",
    "\t\t\ti, j, \n",
    "\t\t\tcorrelation, \n",
    "\t\t\tha = \"center\", \n",
    "\t\t\tva = \"center\", \n",
    "\t\t\tcolor = \"red\" if correlation == 0 else \"w\"\n",
    "\t\t)\n",
    "\n",
    "plt.colorbar(image, ax = axes)\n",
    "\n",
    "plt.show()\n",
    "plt.close()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## aVR Linear Regression using LI and LII"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ aVR_{rec} = - \\frac{LI + LII}{\\sqrt{3}} = -\\frac{1}{\\sqrt{3}}LI - \\frac{1}{\\sqrt{3}}LII $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "linearRegressionModel = LinearRegression()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "linearModel = linearRegressionModel.fit(\n",
    "\tecgDf[[\"LI\", \"LII\"]],\n",
    "\tecgDf[\"aVR\"]\n",
    ")\n",
    "\n",
    "print(np.round(linearModel.coef_, 3))\n",
    "print(np.round(linearModel.intercept_, 3))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aVRRec = linearModel.predict(ecgDf[[\"LI\", \"LII\"]])\n",
    "aVRRec = pd.Series(aVRRec, ecgDf.index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aVRRecCorr = ecgDf[\"aVR\"].corr(\n",
    "\tother = aVRRec, \n",
    "\tmethod = \"pearson\"\n",
    ")\n",
    "\n",
    "aVRRecCorr = np.round(aVRRecCorr, 3)\n",
    "\n",
    "print(aVRRecCorr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "comparativeEcgPlot(\n",
    "\tecg1 = aVRRec,\n",
    "\tlabel1 = \"$aVR_{rec}$\",\n",
    "\t\n",
    "\tecg2 = ecgDf[\"aVR\"],\n",
    "\tlabel2 = \"aVR\",\n",
    "\t\n",
    "\ttitle = \"$aVR_{rec}$ vs aVR. Correlation = \" + str(aVRRecCorr)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### aVR Linear Regression using LI and LiI considering only the QRS complex"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "figure, axes = plt.subplots(\n",
    "\tnrows = 2, \n",
    "\tncols = 1,\n",
    "\tsharex = True,\n",
    ")\n",
    "\n",
    "figure.suptitle(\"Complexos QRS\")\n",
    "figure.supxlabel(\"Amostras\")\n",
    "figure.supylabel(\"Dpp\")\n",
    "\n",
    "axes[0].plot(ecgDf[\"LI\"][100: 500], color = \"blue\")\n",
    "axes[0].set_title(\"LI\")\n",
    "\n",
    "axes[1].plot(ecgDf[\"LII\"][100: 500], color = \"red\")\n",
    "axes[1].set_title(\"LII\")\n",
    "\n",
    "plt.tight_layout()\n",
    "\n",
    "plt.show()\n",
    "\n",
    "plt.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "linearQRSModel = linearRegressionModel.fit(\n",
    "\tecgDf[[\"LI\", \"LII\"]][100: 500],\n",
    "\tecgDf[\"aVR\"][100: 500]\n",
    ")\n",
    "\n",
    "print(np.round(linearQRSModel.coef_, 3))\n",
    "print(np.round(linearQRSModel.intercept_, 3))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aVRRecQRS = linearQRSModel.predict(ecgDf[[\"LI\", \"LII\"]])\n",
    "aVRRecQRS = pd.Series(aVRRecQRS, ecgDf.index)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "aVRRecQRSCorr = ecgDf[\"aVR\"].corr(\n",
    "\tother = aVRRecQRS, \n",
    "\tmethod = \"pearson\"\n",
    ")\n",
    "\n",
    "aVRRecQRSCorr = np.round(aVRRecQRSCorr, 3)\n",
    "\n",
    "print(aVRRecQRSCorr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "comparativeEcgPlot(\n",
    "\tecg1 = aVRRecQRS,\n",
    "\tlabel1 = \"$aVR_{QRS-Rec}$\",\n",
    "\t\n",
    "\tecg2 = ecgDf[\"aVR\"],\n",
    "\tlabel2 = \"aVR\",\n",
    "\t\n",
    "\ttitle = \"$aVR_{QRS-Rec}$ vs aVR. Correlation = \" + str(aVRRecQRSCorr)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ECG synthesis using the best set of leads (I, II, V2) from the neiwan article (2004)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Plot Ecg Function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plotECG(ecgDf): \n",
    "\tfigure, axes = plt.subplots(\n",
    "\t\tnrows = 3,\n",
    "\t\tncols = 4,\n",
    "\t\tsharex = True,\n",
    "\t\tfigsize = (16, 9)\n",
    "\t)\n",
    "\n",
    "\tfigure.suptitle(\"ECG 12-Lead\")\n",
    "\tfigure.supxlabel(\"Amostra\")\n",
    "\tfigure.supylabel(\"Dpp\")\n",
    "\n",
    "\taxes[0, 0].plot(ecgDf[\"LI\"], color = \"#00916E\")\n",
    "\taxes[0, 0].set_title(\"LI\")\n",
    "\n",
    "\taxes[0, 1].plot(ecgDf[\"aVR\"], color = \"black\")\n",
    "\taxes[0, 1].set_title(\"aVR\")\n",
    "\n",
    "\taxes[0, 2].plot(ecgDf[\"V1\"], color = \"#FFCF00\")\n",
    "\taxes[0, 2].set_title(\"V1\")\n",
    "\n",
    "\taxes[0, 3].plot(ecgDf[\"V4\"], color = \"#EE6123\")\n",
    "\taxes[0, 3].set_title(\"V4\")\n",
    "\n",
    "\n",
    "\taxes[1, 0].plot(ecgDf[\"LII\"], color = \"#80A4ED\")\n",
    "\taxes[1, 0].set_title(\"LII\")\n",
    "\n",
    "\taxes[1, 1].plot(ecgDf[\"aVL\"], color = \"#00916E\")\n",
    "\taxes[1, 1].set_title(\"aVL\")\n",
    "\n",
    "\taxes[1, 2].plot(ecgDf[\"V2\"], color = \"#FFCF00\")\n",
    "\taxes[1, 2].set_title(\"V2\")\n",
    "\n",
    "\taxes[1, 3].plot(ecgDf[\"V5\"], color = \"#FA003F\")\n",
    "\taxes[1, 3].set_title(\"V5\")\n",
    "\n",
    "\n",
    "\taxes[2, 0].plot(ecgDf[\"LII\"], color = \"#80A4ED\")\n",
    "\taxes[2, 0].set_title(\"LII\")\n",
    "\n",
    "\taxes[2, 1].plot(ecgDf[\"aVF\"], color = \"#80A4ED\")\n",
    "\taxes[2, 1].set_title(\"aVF\")\n",
    "\n",
    "\taxes[2, 2].plot(ecgDf[\"V3\"], color = \"#EE6123\")\n",
    "\taxes[2, 2].set_title(\"V3\")\n",
    "\n",
    "\taxes[2, 3].plot(ecgDf[\"V6\"], color = \"#FA003F\")\n",
    "\taxes[2, 3].set_title(\"V6\")\n",
    "\n",
    "\tplt.tight_layout(pad = 1.5)\n",
    "\n",
    "\tplt.show()\n",
    "\n",
    "\tplt.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plotECG(ecgDf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plotECG(ecgDf[100: 500])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ecgRecDf = pd.DataFrame().reindex_like(ecgDf)\n",
    "\n",
    "print(ecgRecDf.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ecgRecDf[\"LI\"] = ecgDf[\"LI\"]\n",
    "ecgRecDf[\"LII\"] = ecgDf[\"LII\"]\n",
    "ecgRecDf[\"V2\"] = ecgDf[\"V2\"]\n",
    "\n",
    "print(ecgRecDf.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "recHeaders = set(ecgHeaders) - set([\"LI\", \"LII\", \"V2\", \"sample\"])\n",
    "print(recHeaders)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "regressionDf = pd.DataFrame(\n",
    "\tcolumns = [\"lead\", \"LI\", \"LII\", \"V2\", \"Intercept\"],\n",
    ")\n",
    "\n",
    "for recLead in recHeaders:\n",
    "\trecLinearModel = linearRegressionModel.fit(\n",
    "\t\tX = ecgDf[[\"LI\", \"LII\", \"V2\"]][100: 500], \n",
    "\t\ty = ecgDf[recLead][100: 500]\n",
    "\t)\n",
    "\t\n",
    "\tregressionDf.loc[len(regressionDf)] = [\n",
    "\t\trecLead,\n",
    "\t\trecLinearModel.coef_[0],\n",
    "\t\trecLinearModel.coef_[1],\n",
    "\t\trecLinearModel.coef_[2],\n",
    "\t\trecLinearModel.intercept_\n",
    "\t]\n",
    "\n",
    "\trecLeadSeries = recLinearModel.predict(X = ecgDf[[\"LI\", \"LII\", \"V2\"]])\n",
    "\trecLeadSeries = pd.Series(recLeadSeries, index = ecgDf.index)\n",
    "\t\n",
    "\tecgRecDf[recLead] = recLeadSeries\n",
    "\n",
    "regressionDf = regressionDf.set_index(\"lead\")\n",
    "\n",
    "print(ecgRecDf.head())\n",
    "print(regressionDf.head())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plotECG(ecgRecDf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "plotECG(ecgRecDf[100: 500])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def comparativeFullEcgPlot(ecgA, ecgB):\n",
    "\tfigure, axes = plt.subplots(\n",
    "\t\tnrows = 3,\n",
    "\t\tncols = 4,\n",
    "\t\tsharex = True,\n",
    "\t\tfigsize = (16, 9)\n",
    "\t)\n",
    "\n",
    "\tfigure.suptitle(\"ECG 12-Lead\")\n",
    "\tfigure.supxlabel(\"Amostra\")\n",
    "\tfigure.supylabel(\"Dpp\")\n",
    "\n",
    "\taxes[0, 0].plot(ecgA[\"LI\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[0, 0].plot(ecgB[\"LI\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[0, 0].set_title(\"LI\")\n",
    "\n",
    "\taxes[0, 1].plot(ecgA[\"aVR\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[0, 1].plot(ecgB[\"aVR\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[0, 1].set_title(\"aVR\")\n",
    "\n",
    "\taxes[0, 2].plot(ecgA[\"V1\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[0, 2].plot(ecgB[\"V1\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[0, 2].set_title(\"V1\")\n",
    "\n",
    "\taxes[0, 3].plot(ecgA[\"V4\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[0, 3].plot(ecgB[\"V4\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[0, 3].set_title(\"V4\")\n",
    "\n",
    "\n",
    "\taxes[1, 0].plot(ecgA[\"LII\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[1, 0].plot(ecgB[\"LII\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[1, 0].set_title(\"LII\")\n",
    "\n",
    "\taxes[1, 1].plot(ecgA[\"aVL\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[1, 1].plot(ecgB[\"aVL\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[1, 1].set_title(\"aVL\")\n",
    "\n",
    "\taxes[1, 2].plot(ecgA[\"V2\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[1, 2].plot(ecgB[\"V2\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[1, 2].set_title(\"V2\")\n",
    "\n",
    "\taxes[1, 3].plot(ecgA[\"V5\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[1, 3].plot(ecgB[\"V5\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[1, 3].set_title(\"V5\")\n",
    "\n",
    "\n",
    "\taxes[2, 0].plot(ecgA[\"LII\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[2, 0].plot(ecgB[\"LII\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[2, 0].set_title(\"LII\")\n",
    "\n",
    "\taxes[2, 1].plot(ecgA[\"aVF\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[2, 1].plot(ecgB[\"aVF\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[2, 1].set_title(\"aVF\")\n",
    "\n",
    "\taxes[2, 2].plot(ecgA[\"V3\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[2, 2].plot(ecgB[\"V3\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[2, 2].set_title(\"V3\")\n",
    "\n",
    "\taxes[2, 3].plot(ecgA[\"V6\"], color = \"blue\", alpha = 0.75)\n",
    "\taxes[2, 3].plot(ecgB[\"V6\"], color = \"red\", alpha = 0.75)\n",
    "\taxes[2, 3].set_title(\"V6\")\n",
    "\n",
    "\tplt.tight_layout(pad = 1.5)\n",
    "\n",
    "\tplt.show()\n",
    "\n",
    "\tplt.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "comparativeFullEcgPlot(ecgDf, ecgRecDf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "comparativeFullEcgPlot(\n",
    "    ecgDf[100: 500], \n",
    "    ecgRecDf[100: 500]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "figure, axes = plt.subplots()\n",
    "\n",
    "axes.axis(\"off\")\n",
    "\n",
    "figure.suptitle(\"Tabelas das regressões usadas para cada derivação\")\n",
    "\n",
    "figure.subplots_adjust(top = .5)\n",
    "\n",
    "plt.table(\n",
    "    cellText = np.round(regressionDf.values, 5),\n",
    "    colLabels = regressionDf.columns,\n",
    "    \n",
    "    rowLabels = regressionDf.index,\n",
    "    \n",
    "\tloc = \"center\",\n",
    ")\n",
    "\n",
    "plt.tight_layout(pad = 1.5)\n",
    "\n",
    "plt.show()\n",
    "\n",
    "plt.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
